#include "UploadWorker.h"

#include <QDateTime>
#include <QDebug>
#include <QNetworkProxy>

#include "../sql/upload_database.h"
#include "ConstData.h"
#include "DeviceManager.h"
#include "common.h"
#define MAX_RETRY_COUNT 3     // 最大重传次数
#define RETRY_INTERVAL 30000  // 重传间隔
namespace Upload {

UploadWorker::UploadWorker(const QString &id, const Config &config, QObject *parent)
    : QObject(parent),
      m_id(id),
      m_config(config),
      m_running(false),
      m_connected(false),
      m_retryCount(0),
      m_maxRetryCount(MAX_RETRY_COUNT),
      m_retryInterval(RETRY_INTERVAL),
      m_currentRecordId(-1)
{
    m_timer = new QTimer(this);
    connect(m_timer, &QTimer::timeout, this, &UploadWorker::uploadData);
    m_timer->setInterval(1000);  // 每秒检查一次，确保准确捕获上传时机

    // 初始化重传定时器
    m_retryTimer = new QTimer(this);
    m_retryTimer->setSingleShot(true);  // 单次触发
    connect(m_retryTimer, &QTimer::timeout, this, &UploadWorker::retryUpload);

    m_socket = new QTcpSocket(this);

    // 禁用代理，避免代理类型冲突
    m_socket->setProxy(QNetworkProxy::NoProxy);

    connect(m_socket, &QTcpSocket::connected, this, &UploadWorker::onConnected);
    connect(m_socket, &QTcpSocket::disconnected, this, &UploadWorker::onDisconnected);
    connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::errorOccurred),
            this, &UploadWorker::onError);
    connect(m_socket, &QTcpSocket::bytesWritten, this, &UploadWorker::onDataSent);
}

UploadWorker::~UploadWorker() { stop(); }

void UploadWorker::start()
{
    if (m_running) return;

    m_running = true;
    emit statusChanged(m_id, true);

    connectToServer();
    // 立即上传一次
    uploadData();

    // 启动定时器
    m_timer->start();

    qDebug() << "UploadWorker started for" << m_id;
}

void UploadWorker::stop()
{
    if (!m_running) return;

    m_running = false;
    m_timer->stop();
    m_retryTimer->stop();  // 停止重传定时器

    if (m_socket->state() != QAbstractSocket::UnconnectedState) {
        m_socket->disconnectFromHost();
    }

    emit statusChanged(m_id, false);
    qDebug() << "UploadWorker stopped for" << m_id;
}

void UploadWorker::uploadData()
{
    if (!m_running || !m_config.enabled) return;

    QDateTime currentDateTime = QDateTime::currentDateTime();
    QTime currentTime = currentDateTime.time();

    // HJ212协议上传时机判断
    bool shouldUpload = false;
    QString dataType;

    // 小时数据：每小时的0分0秒上传
    if (currentTime.minute() == 0 && currentTime.second() == 0) {
        shouldUpload = true;
        dataType = "hour";
        qDebug() << "上传小时数据" << currentDateTime.toString("yyyy-MM-dd hh:mm:ss");

        QString data = buildUploadData();
        qDebug() << "上传小时数据[" << data << "]";
        connectToServer();
        sendDataWithRetry(data);  // 使用带重传功能的发送函数
    }
}

void UploadWorker::connectToServer()
{
    if (m_socket->state() == QAbstractSocket::ConnectedState) {
        m_connected = true;
        return;
    }

    if (m_socket->state() != QAbstractSocket::UnconnectedState) {
        return;  // 正在连接中
    }

    qDebug() << "Connecting to" << m_config.IP << ":" << m_config.port << "for" << m_id;
    m_socket->connectToHost(m_config.IP, m_config.port);
}

void UploadWorker::onConnected()
{
    m_connected = true;
    qDebug() << "Connected to server for" << m_id;
}

void UploadWorker::onDisconnected()
{
    m_connected = false;
    qDebug() << "Disconnected from server for" << m_id;
}

void UploadWorker::onError(QAbstractSocket::SocketError error)
{
    m_connected = false;
    QString errorMsg = m_socket->errorString();
    emit uploadError(m_id, errorMsg);
    qDebug() << "Socket error for" << m_id << ":" << errorMsg;
}

void UploadWorker::onDataSent()
{
    // 数据发送完成后可以断开连接（如果是短连接模式）
    // m_socket->disconnectFromHost();

    emit uploadSuccess(m_id, "Data sent successfully");
}

QString UploadWorker::buildUploadData()
{
    QDateTime currentDateTime = QDateTime::currentDateTime();

    // HJ1404地表水站协议数据包格式
    // ##数据段长度ST=21;CN=命令编号;PW=访问密码;MN=水站唯一标识;Flag=标志位;CP=&&数据区&&校验码\r\n

    QString dataArea;
    // 精确到毫秒的请求编号
    QString qnTime = currentDateTime.toString("yyyyMMddhhmmsszzz");

    // 构建数据区 - 地表水实时数据上传
    dataArea =
        QString("QN=%1;ST=21;CN=2061;PW=123456;MN=%2;Flag=0;CP=&&").arg(qnTime).arg(m_config.MN);

    // 添加数据时间和地表水质数据内容（示例数据）
    QString dataTime = currentDateTime.toString("yyyyMMddhhmmss");
    // 地表水质参数：pH值、溶解氧、浊度、温度等
    QString dataContent = QString("DataTime=%1;").arg(dataTime);

    for (const auto &deviceName : DEVICE_NAMES) {
        auto helper = DeviceManager::instance()->getDeviceHelper(deviceName);
        if (helper && helper->isEnabled() && DEVICE_MAP[deviceName].isShowData) {
            QString encoding = DEVICE_MAP[deviceName].encoding;
            double value = helper->getDeviceData().analyze_lastResult;
            dataContent += QString("%1-Rtd=%2,%3-Flag=N;").arg(encoding).arg(value).arg(encoding);
        }
    }

    dataArea += dataContent + "&&";

    // 计算CRC校验码（HJ212标准CRC算法）
    QString crcData = dataArea.mid(dataArea.indexOf("QN="));
    crcData = crcData.left(crcData.lastIndexOf("&&") + 2);

    // CRC计算
    quint16 crc =
        Common::CRC16_Checkout((unsigned char *)crcData.toUtf8().data(), crcData.length());

    // 组装完整数据包
    QString fullPacket = QString("##%1%2%3\r\n")
                             .arg(QString::number(dataArea.length()).rightJustified(4, '0'))
                             .arg(dataArea)
                             .arg(QString::number(crc, 16).rightJustified(4, '0').toUpper());

    return fullPacket;
}

void UploadWorker::sendDataWithRetry(const QString &data, int recordId)
{
    // 如果没有传入recordId，说明是新的上传请求
    if (recordId <= 0) {
        m_retryCount = 0;      // 重置重传次数
        m_pendingData = data;  // 保存待发送的数据

        // 记录上传开始
        UploadRecord record(m_id, m_config.IP, m_config.port, data, "上传中");
        m_currentRecordId = UploadDatabase::addUploadRecordAndGetId(record);
    } else {
        m_currentRecordId = recordId;
    }

    if (!m_connected || m_socket->state() != QAbstractSocket::ConnectedState) {
        // 连接失败，启动重传
        scheduleRetry("未连接到服务器");
        return;
    }

    QByteArray dataBytes = data.toUtf8();
    qint64 bytesWritten = m_socket->write(dataBytes);

    if (bytesWritten == -1) {
        // 发送失败，启动重传
        scheduleRetry("写入socket失败");
    } else {
        // 发送成功
        if (m_currentRecordId > 0) {
            UploadDatabase::updateUploadStatus(m_currentRecordId, "成功");
        } else {
            UploadRecord successRecord(m_id, m_config.IP, m_config.port, data, "成功");
            UploadDatabase::addUploadRecord(successRecord);
        }

        // 重置重传相关变量
        m_retryCount = 0;
        m_pendingData.clear();
        m_currentRecordId = -1;

        qDebug() << "Sent" << bytesWritten << "bytes for" << m_id;
        emit uploadSuccess(m_id, "Data sent successfully");
    }
}

void UploadWorker::scheduleRetry(const QString &errorMessage)
{
    if (m_retryCount >= m_maxRetryCount) {
        // 达到最大重传次数，放弃重传
        if (m_currentRecordId > 0) {
            QString finalError = QString("重传失败，已达最大重传次数(%1)：%2")
                                     .arg(m_maxRetryCount)
                                     .arg(errorMessage);
            UploadDatabase::updateUploadStatus(m_currentRecordId, "失败", finalError);
        } else {
            UploadRecord failedRecord(m_id, m_config.IP, m_config.port, m_pendingData, "失败",
                                      errorMessage);
            UploadDatabase::addUploadRecord(failedRecord);
        }

        // 重置重传相关变量
        m_retryCount = 0;
        m_pendingData.clear();
        m_currentRecordId = -1;

        qWarning() << "Upload failed after" << m_maxRetryCount << "retries for" << m_id << ":"
                   << errorMessage;
        emit uploadError(m_id, QString("重传失败：%1").arg(errorMessage));
        return;
    }

    // 增加重传次数
    m_retryCount++;

    // 更新数据库记录状态
    if (m_currentRecordId > 0) {
        QString retryStatus = QString("重传中(%1/%2)").arg(m_retryCount).arg(m_maxRetryCount);
        UploadDatabase::updateUploadStatus(m_currentRecordId, retryStatus, errorMessage);
    }

    qDebug() << "Scheduling retry" << m_retryCount << "of" << m_maxRetryCount << "for" << m_id
             << "in" << m_retryInterval << "ms. Error:" << errorMessage;

    // 启动重传定时器
    m_retryTimer->start(m_retryInterval);
}

void UploadWorker::retryUpload()
{
    if (!m_running || m_pendingData.isEmpty()) {
        return;
    }

    qDebug() << "Retrying upload for" << m_id << "(attempt" << m_retryCount + 1 << "of"
             << m_maxRetryCount + 1 << ")";

    // 重新连接并发送数据
    connectToServer();
    sendDataWithRetry(m_pendingData, m_currentRecordId);
}
}  // namespace Upload